package com.mllweb.blog.service.impl;

import com.mllweb.blog.base.BaseService;
import com.mllweb.blog.core.digest.Base64Utils;
import com.mllweb.blog.core.regex.RegexUtils;
import com.mllweb.blog.data.dao.BlogUserDao;
import com.mllweb.blog.data.dao.BlogUserLoginDao;
import com.mllweb.blog.data.orm.BlogUser;
import com.mllweb.blog.data.orm.BlogUserLogin;
import com.mllweb.blog.service.NoticeService;
import com.mllweb.blog.service.RedisService;
import com.mllweb.blog.service.UserService;
import com.mllweb.blog.service.ValidateService;
import com.mllweb.blog.service.state.LoginState;
import com.mllweb.blog.web.dto.User;
import com.mllweb.blog.web.session.SessionKey;
import jdk.nashorn.internal.runtime.regexp.joni.Regex;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.UUID;

@Service
public class UserServiceImpl extends BaseService implements UserService {
    @Autowired
    private BlogUserDao blogUserDao;
    @Autowired
    private BlogUserLoginDao blogUserLoginDao;
    @Autowired
    private ValidateService validateService;
    @Autowired
    private RedisService redisService;
    private final String EMAIL = "email";
    private final String PHONE = "phone";
    private final String USERNAME = "username";

    @Override
    public LoginState login(BlogUserLogin login) {
        BlogUserLogin userLogin = blogUserLoginDao.selectByLoginName(login.getLoginName());
        if (userLogin == null) {
            return LoginState.USER_UNFOUND;
        }
        boolean equals = digest(userLogin, login.getLoginPwd());
        if (equals) {
            BlogUser blogUser = blogUserDao.selectById(userLogin.getUserId());
            User user = new User();
            BeanUtils.copyProperties(blogUser, user);
            user.setBase64Id(Base64Utils.encode(String.valueOf(user.getId()).getBytes()));
            getSession().setAttribute(SessionKey.USER.toString(), user);
            return LoginState.SUCCESS;
        } else {
            return LoginState.PWD_MISTAKE;
        }
    }

    @Transactional
    @Override
    public void register(BlogUser user, BlogUserLogin userLogin) {
        //分析注册方式
        mode(user, userLogin);
        blogUserDao.insert(user);
        //设置登录配置
        userLogin.setUserId(user.getId());
        digest(userLogin);
        blogUserLoginDao.insert(userLogin);
        //是否发送验证短信
        if (userLogin.getLoginMode() == redisService.getLoginMode(EMAIL)) {
            validateService.validate(userLogin.getLoginName());
        }
    }

    /**
     * 对登录密码进行加密保存
     *
     * @param userLogin
     */
    private void digest(BlogUserLogin userLogin) {
        String salt = UUID.randomUUID().toString();
        userLogin.setSalt(salt);
        String pwd = userLogin.getLoginPwd();
        String first = DigestUtils.md5DigestAsHex(pwd.getBytes());
        String second = DigestUtils.md5DigestAsHex((first.concat(salt)).getBytes());
        userLogin.setLoginPwd(second);
    }

    /**
     * 对密码进行验证
     *
     * @param userLogin
     * @return
     */
    private boolean digest(BlogUserLogin userLogin, String pwd) {
        String salt = userLogin.getSalt();
        String first = DigestUtils.md5DigestAsHex(pwd.getBytes());
        String second = DigestUtils.md5DigestAsHex((first.concat(salt)).getBytes());
        return StringUtils.equals(userLogin.getLoginPwd(), second);
    }

    /**
     * 分析登录/注册模式
     *
     * @param userLogin
     */
    private void mode(BlogUser user, BlogUserLogin userLogin) {
        String text = userLogin.getLoginName();
        String mode;
        if (RegexUtils.testEmail(text)) {
            mode = EMAIL;
            user.setEmail(text);
        } else if (RegexUtils.testPhone(text)) {
            mode = PHONE;
            user.setPhone(text);
        } else {
            mode = USERNAME;
            user.setUsername(text);
        }
        userLogin.setLoginMode(redisService.getLoginMode(mode));
    }
}
